package com.whately.core.redis.utils;

import com.whately.core.base.model.RedisKeyBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Component
public class RedisCacheSetUtils {

    private final Logger logger = LoggerFactory.getLogger(RedisCacheSetUtils.class);

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**************************************************************************
     *     set
     *************************************************************************/
    public Set<String> difference(RedisKeyBuilder key, RedisKeyBuilder otherKey) {
        return redisTemplate.opsForSet().difference(key.getKey(), otherKey.getKey());
    }

    public Set<String> difference(RedisKeyBuilder key, Collection<RedisKeyBuilder> otherKeys) {
        return redisTemplate.opsForSet().difference(key.getKey(), convert(otherKeys));
    }

    public Long differenceAndStore(RedisKeyBuilder key, RedisKeyBuilder otherKey, RedisKeyBuilder destKey) {
        return redisTemplate.opsForSet().differenceAndStore(key.getKey(), otherKey.getKey(), destKey.getKey());
    }

    public Long differenceAndStore(RedisKeyBuilder key, Collection<RedisKeyBuilder> otherKeys, RedisKeyBuilder destKey) {
        return redisTemplate.opsForSet().differenceAndStore(key.getKey(), convert(otherKeys), destKey.getKey());

    }

    public Set<String> intersect(RedisKeyBuilder key, RedisKeyBuilder otherKey) {
        return redisTemplate.opsForSet().intersect(key.getKey(), otherKey.getKey());

    }

    public Set<String> intersect(RedisKeyBuilder key, Collection<RedisKeyBuilder> otherKeys) {
        return redisTemplate.opsForSet().intersect(key.getKey(), convert(otherKeys));

    }

    public Long intersectAndStore(RedisKeyBuilder key, RedisKeyBuilder otherKey, RedisKeyBuilder destKey) {
        return redisTemplate.opsForSet().intersectAndStore(key.getKey(), otherKey.getKey(), destKey.getKey());
    }

    public Long intersectAndStore(RedisKeyBuilder key, Collection<RedisKeyBuilder> otherKeys, RedisKeyBuilder destKey) {
        return redisTemplate.opsForSet().intersectAndStore(key.getKey(), convert(otherKeys), destKey.getKey());

    }

    public Set<String> union(RedisKeyBuilder key, RedisKeyBuilder otherKey) {
        return redisTemplate.opsForSet().union(key.getKey(), otherKey.getKey());
    }

    public Set<String> union(RedisKeyBuilder key, Collection<RedisKeyBuilder> otherKeys) {
        return redisTemplate.opsForSet().union(key.getKey(), convert(otherKeys));
    }

    public Long unionAndStore(RedisKeyBuilder key, RedisKeyBuilder otherKey, RedisKeyBuilder destKey) {
        return redisTemplate.opsForSet().unionAndStore(key.getKey(), otherKey.getKey(), destKey.getKey());

    }

    public Long unionAndStore(RedisKeyBuilder key, Collection<RedisKeyBuilder> otherKeys, RedisKeyBuilder destKey) {
        return redisTemplate.opsForSet().unionAndStore(key.getKey(), convert(otherKeys), destKey.getKey());

    }

    public Long add(RedisKeyBuilder key, String... values) {
        return redisTemplate.opsForSet().add(key.getKey(), values);
    }

    public Boolean isMember(RedisKeyBuilder key, Object o) {
        return redisTemplate.opsForSet().isMember(key.getKey(), o);
    }

    public Set<String> members(RedisKeyBuilder key) {
        return redisTemplate.opsForSet().members(key.getKey());

    }

    public Boolean move(RedisKeyBuilder key, String value, RedisKeyBuilder destKey) {
        return redisTemplate.opsForSet().move(key.getKey(), value, destKey.getKey());

    }

    public String randomMember(RedisKeyBuilder key) {
        return redisTemplate.opsForSet().randomMember(key.getKey());

    }


    public Long remove(RedisKeyBuilder key, Object... values) {
        return redisTemplate.opsForSet().remove(key.getKey(), values);

    }

    public String pop(RedisKeyBuilder key) {
        return redisTemplate.opsForSet().pop(key.getKey());
    }

    public Long size(RedisKeyBuilder key) {
        return redisTemplate.opsForSet().size(key.getKey());

    }

    private List<String> convert(Collection<RedisKeyBuilder> keys){
        return keys.stream().map(RedisKeyBuilder::getKey).collect(Collectors.toList());
    }

}
